package com.njcb.ams.support.beanprocessor;

import com.njcb.ams.support.exception.ExceptionUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.cglib.core.SpringNamingPolicy;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 自定义的spring Bean工厂
 * 用于实例化bean
 * @author liuyanlong
 * @param <T>
 */
public class AmsBusinessBeanFactory<T> implements InitializingBean, FactoryBean<T> {
	private String innerClassName;

	public void setInnerClassName(String innerClassName) {
		this.innerClassName = innerClassName;
	}

	@Override
	@SuppressWarnings("unchecked")
	public T getObject() throws Exception {
		Class<?> innerClass = Class.forName(innerClassName);
		if (innerClass.isInterface()) {
			return (T) AmsInterfaceProxy.newInstance(innerClass);
		} else {
			Enhancer enhancer = new Enhancer();
			enhancer.setSuperclass(innerClass);
			enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
			enhancer.setCallback(new AmsMethodInterceptor());
			return (T) enhancer.create();
		}
	}

	@Override
	public Class<?> getObjectType() {
		try {
			return Class.forName(innerClassName);
		} catch (ClassNotFoundException e) {
			ExceptionUtil.throwAppException("ClassNotFoundException:" + innerClassName);
		}
		return null;
	}

	@Override
	public boolean isSingleton() {
		return true;
	}

	@Override
	public void afterPropertiesSet() throws Exception {
	}

	static class AmsInterfaceProxy implements InvocationHandler {
		private static final Logger logger = LoggerFactory.getLogger(AmsInterfaceProxy.class);

		@Override
		public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
			logger.info("接口代理执行前");
			Object object = method.invoke(proxy, args);
			logger.info("接口代理执行后");
			return object;
		}

		@SuppressWarnings({ "rawtypes", "unchecked" })
		public static <T> T newInstance(Class<T> innerInterface) {
			ClassLoader classLoader = innerInterface.getClassLoader();
			Class[] interfaces = new Class[] { innerInterface };
			AmsInterfaceProxy proxy = new AmsInterfaceProxy();
			return (T) Proxy.newProxyInstance(classLoader, interfaces, proxy);
		}
	}

	class AmsMethodInterceptor implements MethodInterceptor {
		private final Logger logger = LoggerFactory.getLogger(AmsMethodInterceptor.class);
		@Override
		public Object intercept(Object obj, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
			logger.info("类代理执行前");
			Object object = methodProxy.invokeSuper(obj, objects);
			logger.info("类代理执行后");
			return object;
		}
	}
}
